Completed
Push — master ( 50381b...d599db )
by Jeff
04:14
created

designer.js ➔ handleMoveStart   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
c 0
b 0
f 0
rs 8.5125
cc 5
nc 5
nop 2
1
/** global: fields, contentTypes, templateId, editFieldUrl, setFieldPosUrl, selfContentIds, currentField */
2
3
// Raphael handler for draw init action
4
// Draws fields
5
function preDraw() {
6
  paper = this;
7
  for (var f in fields) {
8
    if (fields.hasOwnProperty(f)) {
9
      createField(fields[f]);
10
    }
11
  }
12
}
13
14
// Draw single field with associated text and assign handlers
15
function createField(field) {
16
  var r = paper.rect(
17
      Math.round(pW * field.x1),
18
      Math.round(pH * field.y1),
19
      Math.round(pW * (field.x2 - field.x1)),
20
      Math.round(pH * (field.y2 - field.y1))
21
    )
22
    .attr('fill', '#F00')
23
    .attr('opacity', 0.7)
24
    .attr('stroke', '#FFF')
25
    .attr('stroke-width', 6);
26
  r.field = field;
27
28
  var t = paper.text(
29
    Math.round(pW * field.x1 + 6),
30
    Math.round(pH * field.y1 + 8),
31
    field.contentTypes ? field.contentTypes.map(function(c) {
32
      return contentTypes[c.id];
33
    }).join(' - ') : ''
34
  );
35
  r.text = t.attr('text-anchor', 'start');
36
  r.drag(handleMove, handleMoveStart, handleMoveEnd);
37
}
38
39
// Create a new field and store it
40
function addField($btn) {
41
  $.ajax({
42
    url: $btn.attr('href'),
43
    type: 'GET',
44
    data: {
45
      templateId: templateId
46
    },
47
    success: function(res) {
48
      if (res.success) {
49
        createField(res.field);
50
      } else {
51
        alert(res.message);
52
      }
53
    }
54
  });
55
}
56
57
// Show field modification popover
58
function editField() {
59
  if (!this.moved) {
60
    $("#field-modal").html();
61
    $.get(editFieldUrl + this.field.id, function(html) {
62
      $("#field-modal").html($(html));
63
      $('.modal').modal('show');
64
    });
65
  }
66
}
67
68
// Send field updates to backend
69
function updateField(id) {
70
  $.ajax({
71
    url: 'get-field',
72
    type: 'GET',
73
    data: {
74
      id: id
75
    },
76
    success: function(res) {
77
      if (res.success) {
78
        var field = res.field;
79
        getField(field.id, function(e) {
80
          e.attr('x', Math.round(pW * field.x1));
81
          e.attr('y', Math.round(pH * field.y1));
82
          e.attr('width', Math.round(pW * (field.x2 - field.x1)));
83
          e.attr('height', Math.round(pH * (field.y2 - field.y1)));
84
          e.text.attr('text', field.contentTypes ? field.contentTypes.map(function(c) {
85
            return contentTypes[c.id];
86
          }).join(' - ') : '');
87
        });
88
      }
89
    }
90
  })
91
}
92
93
// Find field based on ID in paper
94
function getField(id, cb) {
95
  paper.forEach(function(e) {
96
    if (e.type == 'rect' && e.field.id * 1 === id) {
97
      cb(e);
98
      return false;
99
    }
100
    return true;
101
  });
102
}
103
104
// Remove a field based on ID
105
function removeField(id) {
106
  getField(id, function(e) {
107
    e.text.remove();
108
    e.remove();
109
  });
110
}
111
112
// Field move handler
113
var resizeMin = 20;
114
115
function handleMove(dx, dy, x, y) {
116
  var oX = this.ox;
117
  var oY = this.oy;
118
  var oH = this.oh;
119
  var oW = this.ow;
120
121
  switch (this.resizing) {
122
    case 'TOP':
123
      if (oH - dy < resizeMin) {
124
        dy = oH - resizeMin;
125
      }
126
      if (oY + dy < 0) {
127
        dy = -oY;
128
      }
129
      oH = oH - dy;
130
      oY = oY + dy;
131
      break;
132
    case 'BOTTOM':
133
      if (oH + dy < resizeMin) {
134
        dy = resizeMin - oH;
135
      }
136
      if (oY + oH + dy > pH) {
137
        dy = pH - oY - oH; // oY + oH + dY = pH -> dY = 
138
      }
139
      oH = oH + dy;
140
      break;
141
    case 'LEFT':
142
      if (oW - dx < resizeMin) {
143
        dx = oW - resizeMin;
144
      }
145
      if (oX + dx < 0) {
146
        dx = -oX;
147
      }
148
      oW = oW - dx;
149
      oX = oX + dx;
150
      break;
151
    case 'RIGHT':
152
      if (oW + dx < resizeMin) {
153
        dx = resizeMin - oW;
154
      }
155
      if (oX + oW + dx > pW) {
156
        dx = pW - oX - oW;
157
      }
158
      oW = oW + dx;
159
      break;
160
    default:
161
      oX = Math.max(0, Math.min(oX + dx, pW - oW));
162
      oY = Math.max(0, Math.min(oY + dy, pH - oH));
163
  }
164
165
  if (oX != this.ox || oY != this.oy || oH != this.oh || oW != this.ow) {
166
    this.moved = true;
167
  }
168
169
  var pos = {
170
    x: oX,
171
    y: oY,
172
    width: oW,
173
    height: oH,
174
  };
175
  this.attr(pos).text.attr({
176
    x: oX + 6,
177
    y: oY + 8
178
  });
179
}
180
181
// Field move start handler
182
var resizeTreshold = 6;
183
184
function handleMoveStart(x, y) {
185
  this.toFront();
186
  this.text.toFront();
187
  this.resizing = null;
188
  this.moved = false;
189
190
  var mX = x - pX;
191
  var mY = y - pY;
192
193
  this.ox = this.attr('x');
194
  this.oy = this.attr('y');
195
  this.ow = this.attr('width');
196
  this.oh = this.attr('height');
197
198
  if (mX - this.ox < resizeTreshold) {
199
    this.resizing = 'LEFT';
200
  } else if (mY - this.oy < resizeTreshold) {
201
    this.resizing = 'TOP';
202
  } else if ((this.ox + this.ow) - mX < resizeTreshold) {
203
    this.resizing = 'RIGHT';
204
  } else if ((this.oy + this.oh) - mY < resizeTreshold) {
205
    this.resizing = 'BOTTOM';
206
  }
207
}
208
209
// Field move end handler
210
function handleMoveEnd() {
211
  if (!this.moved) {
212
    editField.call(this);
213
    return;
214
  }
215
216
  var o = this.field;
217
  o.x1 = this.attr('x') / pW;
218
  o.y1 = this.attr('y') / pH;
219
  o.x2 = (this.attr('x') + this.attr('width')) / pW;
220
  o.y2 = (this.attr('y') + this.attr('height')) / pH;
221
  $.post(setFieldPosUrl + o.id, {
222
    Field: o
223
  });
224
}
225
226
// Field creation on button click
227
$(document).on('click', '.field-add', function() {
228
  addField($(this));
229
  return false;
230
});
231
232
var pW;
233
var pH;
234
var pX;
235
var pY;
236
var paper = null;
237
238
// jQuery load
239
// Setup screen size and init Raphael
240
function load() {
241
  var $b = $('.background-edit');
242
  pW = $b.width();
243
  pH = $b.height();
244
  var offset = $b.offset();
245
  pX = offset.left;
246
  pY = offset.top;
247
  Raphael('design', pW, pH, preDraw);
248
}
249
250
// jQuery on load
251
$(load);
252
253
// Popover submit action
254
// Send data over ajax POST
255
$(document).on('beforeSubmit', '#screen-template-field-form', function() {
256
  var $form = $(this);
257
  if ($form.find('.has-error').length) {
258
    return false;
259
  }
260
261
  $.ajax({
262
    url: $form.attr('action'),
263
    type: $form.attr('method'),
264
    data: $form.serialize(),
265
    success: function(resp) {
266
      if (resp == '') {
267
        $('.modal').modal('hide');
268
        window.location.reload();
269
      } else {
270
        $("#field-modal").html($(resp));
271
        $('.modal').modal('show');
272
      }
273
    }
274
  })
275
  return false;
276
});
277
278
// Field delete handler
279
$(document).on('click', '.field-delete', function() {
280
  var $btn = $(this);
281
  $.ajax({
282
    url: $btn.attr('href'),
283
    type: 'GET',
284
    success: function(resp) {
285
      $('.modal').modal('hide');
286
      if (resp.success) {
287
        removeField(currentField);
288
      } else {
289
        alert(resp.message);
290
      }
291
    }
292
  });
293
  return false;
294
});
295
296
// Disable content type incompatible choices
297
$(document).on('change', '#field-contenttypes input', function() {
298
  var $chk = $(this);
299
  if ($chk.val() in selfContentIds) {
300
    $('#field-contenttypes input').not($chk).prop('checked', false);
301
  } else {
302
    $('#field-contenttypes input').filter(function() {
303
      return $(this).val() in selfContentIds;
304
    }).prop('checked', false);
305
  }
306
});
307